package org.usmile.algorithms.learn.graph.weighted;


import java.util.ArrayList;
import java.util.Collection;
import java.util.Map;
import java.util.TreeMap;

public class WeightedAdjSet {
    private final int v;
    private final TreeMap<Integer, Integer>[] adj;

    private int e;


    @SuppressWarnings("unchecked")
    public WeightedAdjSet(int v) {
        this.v = v;
        this.adj = new TreeMap[v];

        for (int i = 0; i < v; i++) {
            this.adj[i] = new TreeMap<>();
        }
    }

    public int getV() {
        return this.v;
    }

    public int getE() {
        return this.e;
    }

    public void addEdge(int v, int w, int weight) {
        if (w == v || w >= this.v || v >= this.v) {
            return;
        }

        if (adj[v].containsKey(w)) {
            return;
        }

        adj[v].put(w, weight);
        adj[w].put(v, weight);
        e++;
    }

    // 获取指定边的权重值
    public int getWeight(int v, int w) {
        if (hasEdge(v, w)) {
            return adj[v].get(w);
        }

        return -1;
    }

    public boolean hasEdge(int v, int w) {
        if (w >= this.v || v >= this.v) {
            return false;
        }

        return adj[v].containsKey(w);
    }

    public Collection<Integer> adj(int v) {
        if (v >= this.v) {
            return new ArrayList<>();
        }

        return adj[v].keySet();
    }

    public int degree(int v) {
        return adj(v).size();
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append(String.format("顶点数 = %d，边数 = %d \n", v, e));
        for (int v = 0; v < this.v; v++) {
            sb.append(v).append(": ");
            for (Map.Entry<Integer, Integer> entry : adj[v].entrySet()) {
                sb.append("(").append(entry.getKey()).append(", ").append(entry.getValue()).append(")");
            }
            sb.append("\n");
        }
        return sb.toString();
    }

    public static void main(String[] args) {
        WeightedAdjSet adjSet = new WeightedAdjSet(8);
        adjSet.addEdge(0, 1, 1);
        adjSet.addEdge(1, 2, 2);
        adjSet.addEdge(3, 2, 3);
        System.out.println(adjSet.adj(1));
        System.out.println(adjSet);
    }
}